﻿using System;
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
using System.Threading;

using BodaNetCommunications.Utilities.ComTypes;
using BodaNetCommunications.Utilities.DataLibs;
using BodaNetCommunications.Utilities.Locks;
using BodaNetCommunications.Utilities.Results;
using BodaNetCommunications.Utilities.Validations;

using Newtonsoft.Json;

namespace BodaNetCommunications.ModbusTcpComs
{
    /// <summary>
    /// Modbus客户端应用，采集数据
    /// </summary>
    public class BodaModbusTcpClient
    {
        private Socket tcpclient;

        private SimpleHybirdLock InteractiveLock = new SimpleHybirdLock();
        private SimpleHybirdLock InteractiveConnectionLock = new SimpleHybirdLock();

        //
        // 摘要:
        //     发送超时事件
        [JsonProperty(nameof(SendTimeOut))]  // 用于反射获取需要自定义赋值的属性
        [DefaultValue(2000)]  // 用于反射的默认值
        public int SendTimeOut { get; set; } = 2000;

        //
        // 摘要:
        //     接收超时事件
        [JsonProperty(nameof(ReceiveTimeOut))]
        [DefaultValue(2000)]
        public int ReceiveTimeOut { get; set; } = 2000;

        //
        // 摘要:
        //     字节大小端顺序
        [JsonProperty(nameof(DataFormat))]
        [DefaultValue(EndianType.ABCD)]
        public EndianType DataFormat { get; set; } = EndianType.ABCD;

        //
        // 摘要:
        //     接受返回报文等待次数，每次为10ms
        [JsonProperty(nameof(WaitTimes))]
        [DefaultValue(100)]
        public int WaitTimes { get; set; } = 100;

        //
        // 摘要:
        //     从站地址
        [JsonProperty(nameof(SlaveAddress))]
        [DefaultValue(0x01)]
        public byte SlaveAddress { get; set; } = 0x01;

        /// <summary>
        /// 获取或设置起始的地址是否从0开始，默认为True
        /// </summary>
        /// <remarks>
        /// <note type="warning">因为有些设备的起始地址是从1开始的，就要设置本属性为<c>Flase</c></note>
        /// </remarks>
        [JsonProperty(nameof(AddressStartWithZero))]
        [DefaultValue(true)]
        public bool AddressStartWithZero { get; set; } = true;

        /// <summary>
        /// 字符串数据是否按照字来反转
        /// </summary>
        /// <remarks>
        /// 字符串按照2个字节的排列进行颠倒，根据实际情况进行设置
        /// </remarks>
        [JsonProperty(nameof(IsStringReverse))]
        [DefaultValue(false)]
        public bool IsStringReverse { get; set; }

        //
        // 摘要:
        //     连接超时时间
        [JsonProperty(nameof(ConnectTimeOut))]
        [DefaultValue(2000)]
        public int ConnectTimeOut { get; set; } = 2000;

        public bool IsConnecting { get; set; }

        /// <summary>
        /// 之前连接过，说明可以重新连接，或者需要断线重新
        /// </summary>
        private bool _connectedOnce = false;

        private string _ip = string.Empty;
        private int _port = 0;
        private int _failedConnectionCount = 0;

        //
        // 摘要:
        //     建立Socket连接
        //
        // 参数:
        //   ip:
        //     IP地址
        //
        //   port:
        //     端口号
        public BodaResult<bool> Connect(string ip, string port)
        {
            BodaResult<bool> bodaResult = new BodaResult<bool>();

            // 验证IP
            ip = ip?.Trim();
            if (string.IsNullOrEmpty(ip))
            {
                bodaResult.IsSuccess = false;
                bodaResult.Message = $"IP不能为空";
                return bodaResult;
            }
            var validIp = ValidationUtility.IsValidIpAddress(ip);
            var ipParse = IPAddress.TryParse(ip, out var ipTemp);
            if (false == validIp || false == ipParse)
            {
                bodaResult.IsSuccess = false;
                bodaResult.Message = $"IP【{ip}】不符合IP的规则";
                return bodaResult;
            }

            // 验证Port
            var portParse = int.TryParse(port, out var portTemp);
            if (false == portParse || portTemp <= 0 || portTemp >= 65535)
            {
                bodaResult.IsSuccess = false;
                bodaResult.Message = $"Port【{port}】不符合Port的规则";
                return bodaResult;
            }

            try
            {
                // 如果已经连接了，就不需要继续连接了
                if (tcpclient != null && tcpclient.Connected)
                {
                    bodaResult.IsSuccess = tcpclient.Connected;
                    bodaResult.Message = "当前客户端已经连接，不需要重复连接";
                    return bodaResult;
                }
                // 正在连接中，就不需要重复连接了
                if (IsConnecting)
                {
                    bodaResult.IsSuccess = false;
                    bodaResult.Message = "正在连接中，不需要重复连接... ...";
                    return bodaResult;
                }

                InteractiveConnectionLock.Enter();
                IsConnecting = true;

                _ip = ip;
                _port = portTemp;

                tcpclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
                tcpclient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ReceiveTimeOut);
                tcpclient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, SendTimeOut);
                IPEndPoint remoteEP = new IPEndPoint(ipTemp, portTemp);
                IAsyncResult asyncResult = tcpclient.BeginConnect(remoteEP, null, null);
                var connectionResult = asyncResult.AsyncWaitHandle.WaitOne(ConnectTimeOut, exitContext: true);
                if (!asyncResult.IsCompleted)
                {
                    DisConnect();
                    bodaResult.Message = "连接超时失败";
                    bodaResult.IsSuccess = false;
                }
                else
                {
                    if (connectionResult && tcpclient.Connected)
                    {
                        bodaResult.Message = "连接成功";
                        bodaResult.IsSuccess = true;

                        _connectedOnce = true;
                    }
                    else
                    {
                        bodaResult.Message = "连接未超时，但是socket连接失败";
                        bodaResult.IsSuccess = false;
                    }
                }
            }
            catch (Exception ex)
            {
                bodaResult.IsSuccess = false;
                bodaResult.Message = $"连接出错， 原因: {ex.Message}";
            }
            finally
            {
                InteractiveConnectionLock.Leave();
                IsConnecting = false;
            }

            return bodaResult;
        }

        public bool IsConnected => tcpclient != null && tcpclient.Connected;

        //
        // 摘要:
        //     断开连接
        public void DisConnect()
        {
            try
            {
                if (tcpclient != null)
                {
                    tcpclient.Shutdown(SocketShutdown.Both);
                    tcpclient.Close();
                    tcpclient.Dispose();
                }
            }
            finally
            {
                tcpclient = null;
            }
        }

        //
        // 摘要:
        //     读输出线圈 功能0x01
        //
        // 参数:
        //   iAddress:
        //
        //   iLength:
        public BodaResult<byte[]> ReadOutputStatus(int iAddress, int iLength)
        {
            BodaResult<byte[]> result = new BodaResult<byte[]>();
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            1
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)(iLength / 256));
            byteArray.Add((byte)(iLength % 256));
            result = SendAndReceive(byteArray.array);
            if (result.IsSuccess == false)
            {
                return result;
            }
            var array = result.Content;

            int num = iLength % 8 != 0 ? iLength / 8 + 1 : iLength / 8;
            // 如果读取数据长度和需求的不一致，则需要截取字节数据，因为可能需要10个位；但是只能读取2个字节，需要截取需要的10个位数据
            if (num == array[8])
            {
                var arrOffset = ByteArrayLib.GetByteArray(array, 9, num);
                result.Content = arrOffset;
            }

            return result;
        }

        //
        // 摘要:
        //     读输入线圈 功能0x02
        //
        // 参数:
        //   iAddress:
        //
        //   iLength:
        public BodaResult<byte[]> ReadInputStatus(int iAddress, int iLength)
        {
            BodaResult<byte[]> result = new BodaResult<byte[]>();
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            2
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)(iLength / 256));
            byteArray.Add((byte)(iLength % 256));
            result = SendAndReceive(byteArray.array);
            if (result.IsSuccess == false)
            {
                return result;
            }
            var array = result.Content;

            int num = iLength % 8 != 0 ? iLength / 8 + 1 : iLength / 8;
            if (num == array[8])
            {
                var arrOffset = ByteArrayLib.GetByteArray(array, 9, num);
                result.Content = arrOffset;
            }

            return result;
        }

        //
        // 摘要:
        //     读保持型寄存器 功能码0x03
        //
        // 参数:
        //   iAddress:
        //
        //   iLength:
        public BodaResult<byte[]> ReadKeepReg(int iAddress, int iLength)
        {
            BodaResult<byte[]> result = new BodaResult<byte[]>();
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            3
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)(iLength / 256));
            byteArray.Add((byte)(iLength % 256));
            result = SendAndReceive(byteArray.array);
            if (result.IsSuccess == false)
            {
                return result;
            }
            var array = result.Content;
            int num = iLength * 2;
            if (array.Length == 9 + num)
            {
                if (num == array[8])
                {
                    var arrOffset = ByteArrayLib.GetByteArray(array, 9, num);
                    result.Content = arrOffset;
                }

                return result;
            }

            // 数据长度不对，则返回空值
            result.IsSuccess = false;
            result.Content = null;
            return result;
        }

        //
        // 摘要:
        //     读输入寄存器 功能码0x04
        //
        // 参数:
        //   iAddress:
        //
        //   iLength:
        public BodaResult<byte[]> ReadInputReg(int iAddress, int iLength)
        {
            BodaResult<byte[]> result = new BodaResult<byte[]>();
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            4
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)(iLength / 256));
            byteArray.Add((byte)(iLength % 256));
            result = SendAndReceive(byteArray.array);
            if (result.IsSuccess == false)
            {
                return result;
            }
            var array = result.Content;
            int num = iLength * 2;
            if (array.Length == 9 + num)
            {
                if (num == array[8])
                {
                    var arrOffset = ByteArrayLib.GetByteArray(array, 9, num);
                    result.Content = arrOffset;
                }

                return result;
            }

            // 数据长度不对，则返回空值
            result.IsSuccess = false;
            result.Content = null;
            return result;
        }

        //
        // 摘要:
        //     强制输出线圈 功能码0x05
        //
        // 参数:
        //   iAddress:
        //
        //   Value:
        public BodaResult<bool> ForceCoil(int iAddress, bool Value)
        {
            BodaResult<bool> result = new BodaResult<bool>();
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            5
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            if (Value)
            {
                byteArray.Add(byte.MaxValue);
            }
            else
            {
                byteArray.Add(0);
            }

            byteArray.Add(0);

            var resultArray = SendAndReceive(byteArray.array);
            if (resultArray.IsSuccess == false)
            {
                result.IsSuccess = false;
                result.Content = false;
                result.Message = resultArray.Message;
                result.ErrorCode = resultArray.ErrorCode;
                return result;
            }

            var array = resultArray.Content;
            byte[] byteArray2 = ByteArrayLib.GetByteArray(array, 0, 12);
            result.IsSuccess = true;
            result.Content = ByteArrayLib.ByteArrayEquals(byteArray2, byteArray.array);
            return result;
        }

        //
        // 摘要:
        //     预置双字寄存器 功能码0x10
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetBoolReg(string iAddress, bool SetValue)
        {
            BodaResult<bool> result = new BodaResult<bool>();
            if (!iAddress.Contains('.'))
            {
                result.Message = "地址iAddress输入参数不含有.";
                return result;
            }

            string[] array = iAddress.Split('.');
            if (array.Length != 2)
            {
                result.Message = $"SetValue输入参数的长度为{array.Length}";
                return result;
            }

            int iAddress2 = int.Parse(array[0]);
            int num = int.Parse(array[1]);
            if (num >= 16 || num < 0)
            {
                result.Message = $"iAddress输入参数的中bit的数值不符合字节的要求，必须在[0,15]之间";
                return result;
            }

            var array2Result = ReadKeepReg(iAddress2, 1);
            if (array2Result.IsSuccess == false)
            {
                result.Message = array2Result.Message;
                result.ErrorCode = array2Result.ErrorCode;
                return result;
            }
            var array2 = array2Result.Content;
            if (array2.Length != 2)
            {
                result.Content = false;
                result.Message = "预置双字寄存器的读取数据结果的长度不等于2";
                return result;
            }

            return PreSetSingleReg(iAddress2, ShortLib.SetbitValueFrom2ByteArray(array2, num, SetValue, DataFormat));
        }

        public BodaResult<bool> ForceMultiCoil(int iAddress, bool[] SetValue)
        {
            BodaResult<bool> result = new BodaResult<bool>();
            byte[] byteArrayFromBoolArray = ByteArrayLib.GetByteArrayFromBoolArray(SetValue);
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[4]);
            int num = 7 + byteArrayFromBoolArray.Length;
            byteArray.Add((byte)(num / 256));
            byteArray.Add((byte)(num % 256));
            byteArray.Add(new byte[2]
            {
            (byte)SlaveAddress,
            15
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)(SetValue.Length / 256));
            byteArray.Add((byte)(SetValue.Length % 256));
            byteArray.Add((byte)byteArrayFromBoolArray.Length);
            byteArray.Add(byteArrayFromBoolArray);
            var arrayResult = SendAndReceive(byteArray.array);
            if (arrayResult.IsSuccess)
            {
                var array = arrayResult.Content;
                byte[] byteArray2 = ByteArrayLib.GetByteArray(byteArray.array, 0, 12);
                byteArray2[4] = 0;
                byteArray2[5] = 6;
                result.Content = ByteArrayLib.ByteArrayEquals(byteArray2, array);
                result.IsSuccess = true;
            }

            return result;
        }

        //
        // 摘要:
        //     预置单个寄存器 功能码0x06
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetSingleReg(int iAddress, short SetValue)
        {
            BodaResult<bool> result = new BodaResult<bool>();
            byte[] array = null;
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            6
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add(ByteArrayLib.GetByteArrayFromShort(SetValue));
            var resultArray = SendAndReceive(byteArray.array);
            if (resultArray.IsSuccess == false)
            {
                result.IsSuccess = false;
                result.Content = false;
                result.Message = resultArray.Message;
                result.ErrorCode = resultArray.ErrorCode;
                return result;
            }

            var array2 = resultArray.Content;
            array = ByteArrayLib.GetByteArray(array2, 0, 12);
            byte[] byteArray2 = ByteArrayLib.GetByteArray(byteArray.array, 0, 12);
            byteArray2[5] = 6;
            result.Content = ByteArrayLib.ByteArrayEquals(array, byteArray2);
            result.IsSuccess = true;
            return result;
        }

        //
        // 摘要:
        //     预置单个寄存器 功能码0x06
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetSingleReg(int iAddress, ushort SetValue)
        {
            BodaResult<bool> result = new BodaResult<bool>();
            byte[] array = null;
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[8]
            {
            0,
            0,
            0,
            0,
            0,
            6,
            (byte)SlaveAddress,
            6
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add(ByteArrayLib.GetByteArrayFromUShort(SetValue));
            var resultArray = SendAndReceive(byteArray.array);
            if (resultArray.IsSuccess == false)
            {
                result.IsSuccess = false;
                result.Content = false;
                result.Message = resultArray.Message;
                result.ErrorCode = resultArray.ErrorCode;
                return result;
            }
            var array2 = resultArray.Content;

            array = ByteArrayLib.GetByteArray(array2, 0, 12);
            byte[] byteArray2 = ByteArrayLib.GetByteArray(byteArray.array, 0, 12);
            byteArray2[5] = 6;
            result.Content = ByteArrayLib.ByteArrayEquals(array, byteArray2);
            result.IsSuccess = true;
            return result;
        }

        public BodaResult<bool> PreSetMultiByteArray(int iAddress, byte[] SetValue)
        {
            BodaResult<bool> result = new BodaResult<bool>();
            if (SetValue == null || SetValue.Length == 0 || SetValue.Length % 2 == 1)
            {
                result.IsSuccess = false;
                result.Content = false;
                result.Message = "SetValue输入的数量列表为空，或者数量为奇数";
                return result;
            }

            int num = SetValue.Length / 2;
            ByteArray byteArray = new ByteArray();
            byteArray.Add(new byte[4]);
            int num2 = 7 + SetValue.Length;
            byteArray.Add((byte)(num2 / 256));
            byteArray.Add((byte)(num2 % 256));
            byteArray.Add(new byte[2]
            {
            (byte)SlaveAddress,
            16
            });
            byteArray.Add((byte)(iAddress / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)(num / 256));
            byteArray.Add((byte)(num % 256));
            byteArray.Add((byte)SetValue.Length);
            byteArray.Add(SetValue);
            BodaResult<byte[]> arrayResult = SendAndReceive(byteArray.array);
            if (arrayResult.IsSuccess)
            {
                var array = arrayResult.Content;
                byte[] byteArray2 = ByteArrayLib.GetByteArray(byteArray.array, 0, 12);
                byteArray2[4] = 0;
                byteArray2[5] = 6;
                result.Content = ByteArrayLib.ByteArrayEquals(byteArray2, array);
                result.IsSuccess = true;
                return result;
            }

            return result;
        }

        //
        // 摘要:
        //     写入浮点型数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, float SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromFloat(SetValue));
        }

        //
        // 摘要:
        //     写入Int32型数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, int SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromInt(SetValue));
        }

        //
        // 摘要:
        //     写入UInt32型数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, uint SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromUInt(SetValue));
        }

        //
        // 摘要:
        //     写入Float数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, float[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromFloatArray(SetValue));
        }

        //
        // 摘要:
        //     写入Int32数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, int[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromIntArray(SetValue));
        }

        //
        // 摘要:
        //     写入Int16数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, short[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromShortArray(SetValue));
        }

        //
        // 摘要:
        //     写入UInt32数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, uint[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromUIntArray(SetValue));
        }

        //
        // 摘要:
        //     写入UInt16数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, ushort[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromUShortArray(SetValue));
        }

        //
        // 摘要:
        //     写入Int64类型数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, long SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromLong(SetValue));
        }

        //
        // 摘要:
        //     写入UInt64类型数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, ulong SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromULong(SetValue));
        }

        //
        // 摘要:
        //     写入Double类型数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, double SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromDouble(SetValue));
        }

        //
        // 摘要:
        //     写入Int64数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, long[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromLongArray(SetValue));
        }

        //
        // 摘要:
        //     写入UInt64数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, ulong[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromULongArray(SetValue));
        }

        //
        // 摘要:
        //     写入Double数组数据
        //
        // 参数:
        //   iAddress:
        //
        //   SetValue:
        public BodaResult<bool> PreSetMultiReg(int iAddress, double[] SetValue)
        {
            return PreSetMultiByteArray(iAddress, ByteArrayLib.GetByteArrayFromDoubleArray(SetValue));
        }

        //
        // 摘要:
        //     发送报文并接收返回值
        //
        // 参数:
        //   SendByte:
        private BodaResult<byte[]> SendAndReceive(byte[] SendByte)
        {
            InteractiveLock.Enter();

            BodaResult<byte[]> result = new BodaResult<byte[]>();
            try
            {
                bool state = false;
                if (tcpclient != null)
                {
                    bool state1 = tcpclient.Connected;
                    bool state2 = tcpclient.Poll(1, SelectMode.SelectRead);
                    bool state3 = tcpclient.Poll(1, SelectMode.SelectWrite);
                    state = !(!state1 || (state2 && state3));
                }

                //  bool state = !(!socket.Connected || (socket.Poll(1, SelectMode.SelectRead) && socket.Poll(1, SelectMode.SelectWrite) && (socket.Available == 0)));
                // 断线重连机制
                if (state == false)
                {
                    _failedConnectionCount++;

                    var connectionRes = Connect(_ip, _port.ToString());
                    if (connectionRes.IsSuccess)
                    {
                        result.Message = $"断线重连失败【{_failedConnectionCount}】次后重连成功";
                        _failedConnectionCount = 0;
                        Thread.Sleep(10);
                    }
                    else
                    {
                        result.IsSuccess = false;
                        result.Message = $"断线重连失败【{_failedConnectionCount}】次，原因: {connectionRes.Message}";
                        return result;
                    }
                }

                tcpclient.Send(SendByte, SendByte.Length, SocketFlags.None);
                Thread.Sleep(10);
                int available = tcpclient.Available;
                int num = 0;
                while (available == 0)
                {
                    num++;
                    // 延迟代码需要放在tcpclient.Available上面，否则会出现接收不到数据的问题
                    Thread.Sleep(1);
                    available = tcpclient.Available;
                    if (num > WaitTimes)
                    {
                        break;
                    }
                }

                byte[] array = new byte[available];

                if (available == 0)
                {
                    result.IsSuccess = false;
                    result.Message = $"连接的Available结果为【{available}】";
                }
                else
                {
                    tcpclient.Receive(array, available, SocketFlags.None);

                    result.IsSuccess = true;
                    result.Content = array;
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }
            finally
            {
                InteractiveLock.Leave();
            }
            return result;
        }
    }
}